package com.xxl.job.admin.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxl.job.admin.controller.annotation.PermissionLimit;
import com.xxl.job.admin.controller.interceptor.PermissionInterceptor;
import com.xxl.job.admin.core.exception.XxlJobException;
import com.xxl.job.admin.core.model.XxlJobAlarmConfig;
import com.xxl.job.admin.core.model.XxlJobAlarmRecord;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.dao.XxlJobAlarmConfigDao;
import com.xxl.job.admin.dao.XxlJobAlarmRecordDao;
import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.dao.XxlJobInfoDao;
import com.xxl.job.core.biz.model.ReturnT;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author chenlinqing
 * @description:
 * @date: 2025/8/26 9:16
 */
@Controller
@RequestMapping("/alarm")
public class JobAlarmController {

    @Resource
    private XxlJobAlarmConfigDao xxlJobAlarmConfigDao;
    @Resource
    private XxlJobAlarmRecordDao xxlJobAlarmRecordDao;
    @Resource
    private XxlJobGroupDao xxlJobGroupDao;
    @Resource
    public XxlJobInfoDao xxlJobInfoDao;

    @RequestMapping
    public String index() {
        return "alarm/alarm.index";
    }

    @RequestMapping("/config/list")
    @ResponseBody
    @PermissionLimit(adminuser = true)
    public Map<String, Object> pageList() {
        List<XxlJobAlarmConfig> list = xxlJobAlarmConfigDao.selectList(null);
        // package result
        Map<String, Object> maps = new HashMap<String, Object>();
        // 总记录数
        maps.put("recordsTotal", list.size());
        // 过滤后的总记录数
        maps.put("recordsFiltered", list.size());
        // 分页列表
        maps.put("data", list);
        return maps;
    }

    @RequestMapping("/config/add")
    @ResponseBody
    @PermissionLimit(adminuser = true)
    @Transactional(rollbackFor = Exception.class)
    public ReturnT<String> add(XxlJobAlarmConfig xxlJobAlarmConfig) {
        if (!validAlarmTos(xxlJobAlarmConfig.getAlarmType(), xxlJobAlarmConfig.getAlarmTos())) {
            return new ReturnT<String>(500, I18nUtil.getString("alarm_tos_format_error"));
        }
        LambdaQueryWrapper<XxlJobAlarmConfig> queryWrapper = Wrappers.lambdaQuery(XxlJobAlarmConfig.class)
                .eq(XxlJobAlarmConfig::getAlarmType, xxlJobAlarmConfig.getAlarmType());
        if (xxlJobAlarmConfigDao.selectCount(queryWrapper) > 0) {
            return new ReturnT<String>(500, I18nUtil.getString("alarm_config_type_unique_error"));
        }
        xxlJobAlarmConfigDao.insert(xxlJobAlarmConfig);
        return ReturnT.SUCCESS;
    }

    @RequestMapping("/config/update")
    @ResponseBody
    @PermissionLimit(adminuser = true)
    @Transactional(rollbackFor = Exception.class)
    public ReturnT<String> update(XxlJobAlarmConfig xxlJobAlarmConfig) {
        if (!validAlarmTos(xxlJobAlarmConfig.getAlarmType(), xxlJobAlarmConfig.getAlarmTos())) {
            return new ReturnT<String>(500, I18nUtil.getString("alarm_tos_format_error"));
        }
        xxlJobAlarmConfigDao.updateById(xxlJobAlarmConfig);
        return ReturnT.SUCCESS;
    }

    @RequestMapping("/config/delete")
    @ResponseBody
    @PermissionLimit(adminuser = true)
    @Transactional(rollbackFor = Exception.class)
    public ReturnT<String> delete(@RequestParam("id") Integer id) {
        xxlJobAlarmConfigDao.deleteById(id);
        return ReturnT.SUCCESS;
    }

    /**
     * 预警接收方检查
     *
     * @return
     */
    private boolean validAlarmTos(Integer alarmType, String alarmTos) {
        if (StringUtils.hasLength(alarmTos)) {
            // 邮件
            if (alarmType == 4) {
                String emailMatcher = "[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+";
                for (String str : alarmTos.split(",")) {
                    if (!Pattern.matches(emailMatcher, str)) {
                        return false;
                    }
                }
            } else {
                for (String str : alarmTos.split(",")) {
                    if (!str.startsWith("http")) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    @RequestMapping("/record")
    public String recordIndex(HttpServletRequest request, Model model) {
        // 执行器列表
        List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();

        // filter group
        List<XxlJobGroup> jobGroupList = PermissionInterceptor.filterJobGroupByRole(request, jobGroupList_all);
        if (jobGroupList == null || jobGroupList.size() == 0) {
            throw new XxlJobException(I18nUtil.getString("jobgroup_empty"));
        }

        model.addAttribute("JobGroupList", jobGroupList);
        return "alarm/record.index";
    }


    @RequestMapping("/record/page")
    @ResponseBody
    @PermissionLimit(adminuser = true)
    public Map<String, Object> recordPageList(@RequestParam(value = "start", required = false, defaultValue = "1") int start,
                                              @RequestParam(value = "length", required = false, defaultValue = "10") int length,
                                              @RequestParam(value = "jobGroup", required = false) Long jobGroup,
                                              @RequestParam(value = "jobId", required = false) Long jobId,
                                              @RequestParam(value = "alarmType", required = false) Integer alarmType,
                                              @RequestParam(value = "alarmStatus", required = false) Integer alarmStatus) {
        Page<XxlJobAlarmRecord> page = new Page<>(start, length);
        LambdaQueryWrapper<XxlJobAlarmRecord> queryWrapper = Wrappers.lambdaQuery(XxlJobAlarmRecord.class)
                .eq(jobGroup != null && jobGroup > 0, XxlJobAlarmRecord::getJobGroupId, jobGroup)
                .eq(jobId != null && jobId > 0, XxlJobAlarmRecord::getJobId, jobId)
                .eq(alarmType != null, XxlJobAlarmRecord::getAlarmType, alarmType)
                .eq(alarmStatus != null, XxlJobAlarmRecord::getAlarmStatus, alarmStatus);
        Page<XxlJobAlarmRecord> result = xxlJobAlarmRecordDao.selectPage(page, queryWrapper);

        result.getRecords().stream().forEach(record -> {
            XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(record.getJobId());
            if (xxlJobInfo != null) {
                record.setJobName(xxlJobInfo.getJobDesc());
                record.setJobHandler(xxlJobInfo.getExecutorHandler());
            }
            XxlJobGroup jobGroupInfo=xxlJobGroupDao.load(record.getJobGroupId());
            if (jobGroupInfo != null) {
                record.setJobGroupName(jobGroupInfo.getTitle());
            }
        });

        // package result
        Map<String, Object> maps = new HashMap<String, Object>();
        // 总记录数
        maps.put("recordsTotal", result.getTotal());
        // 过滤后的总记录数
        maps.put("recordsFiltered", result.getRecords().size());
        // 分页列表
        maps.put("data", result.getRecords());
        return maps;
    }
}
